import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';

export interface ApiEndpoint {
  name: string;
  path: string;
  method: string;
  description: string;
  parameters: ApiParameter[];
  returnType: string;
  returnDescription: string;
  examples: ApiExample[];
  filePath: string;
  lineNumber: number;
}

export interface ApiParameter {
  name: string;
  type: string;
  description: string;
  required: boolean;
  defaultValue?: string;
  source?: string; // 'path', 'query', 'body', 'header', 'attribute', 'session'
}

export interface ApiExample {
  title: string;
  description: string;
  code: string;
  language: string;
}

export interface ApiDocumentation {
  projectName: string;
  projectDescription: string;
  endpoints: ApiEndpoint[];
  generatedAt: Date;
}

let extensionContext: vscode.ExtensionContext;

export function activate(context: vscode.ExtensionContext) {
  extensionContext = context;
  console.log('API Documentation Generator is now active!');

  // Register commands
  const generateDocsCommand = vscode.commands.registerCommand('api-doc-generator.generateDocs', async () => {
    await generateApiDocumentation();
  });

  const exportMarkdownCommand = vscode.commands.registerCommand('api-doc-generator.exportMarkdown', async () => {
    await exportToMarkdown();
  });

  context.subscriptions.push(generateDocsCommand, exportMarkdownCommand);
}

export function deactivate() {}

async function generateApiDocumentation(): Promise<void> {
  try {
    const workspaceFolders = vscode.workspace.workspaceFolders;
    if (!workspaceFolders) {
      vscode.window.showErrorMessage('No workspace folder found. Please open a project folder.');
      return;
    }

    const workspaceFolder = workspaceFolders[0];
    const projectPath = workspaceFolder.uri.fsPath;
    const projectName = path.basename(projectPath);

    vscode.window.showInformationMessage('Starting API documentation generation...');

    const endpoints: ApiEndpoint[] = [];
    const files = await findSourceFiles(projectPath);
    
    for (const file of files) {
      const fileEndpoints = await parseFile(file);
      endpoints.push(...fileEndpoints);
    }

    const documentation: ApiDocumentation = {
      projectName,
      projectDescription: `API documentation for ${projectName}`,
      endpoints,
      generatedAt: new Date()
    };

    // Store documentation in extension context
    extensionContext.globalState.update('apiDocumentation', documentation);

    vscode.window.showInformationMessage(
      `Generated documentation for ${endpoints.length} endpoints from ${files.length} files.`
    );

    // Show results in a new document
    await showDocumentationResults(documentation);

  } catch (error) {
    vscode.window.showErrorMessage(`Error generating documentation: ${error}`);
  }
}

async function exportToMarkdown(): Promise<void> {
  try {
    const documentation = extensionContext.globalState.get<ApiDocumentation>('apiDocumentation');
    
    if (!documentation) {
      vscode.window.showErrorMessage('No documentation found. Please generate documentation first.');
      return;
    }

    const workspaceFolders = vscode.workspace.workspaceFolders;
    if (!workspaceFolders) {
      vscode.window.showErrorMessage('No workspace folder found.');
      return;
    }

    const workspaceFolder = workspaceFolders[0];
    const outputPath = path.join(workspaceFolder.uri.fsPath, 'API_Documentation.md');

    const markdownContent = generateMarkdown(documentation);
    fs.writeFileSync(outputPath, markdownContent, 'utf8');

    vscode.window.showInformationMessage(
      `API documentation exported to: ${outputPath}`
    );

    // Open the generated file
    const document = await vscode.workspace.openTextDocument(outputPath);
    await vscode.window.showTextDocument(document);

  } catch (error) {
    vscode.window.showErrorMessage(`Error exporting to markdown: ${error}`);
  }
}

async function findSourceFiles(projectPath: string): Promise<string[]> {
  const files: string[] = [];
  const supportedExtensions = ['.java', '.py', '.js', '.ts', '.jsx', '.tsx', '.graphql', '.gql', '.graphqls'];
  
  async function scanDirectory(dir: string) {
    try {
      const entries = fs.readdirSync(dir, { withFileTypes: true });
      
      for (const entry of entries) {
        const fullPath = path.join(dir, entry.name);
        
        if (entry.isDirectory()) {
          if (!entry.name.startsWith('.') && entry.name !== 'node_modules') {
            await scanDirectory(fullPath);
          }
        } else if (entry.isFile()) {
          const ext = path.extname(entry.name).toLowerCase();
          if (supportedExtensions.includes(ext)) {
            files.push(fullPath);
          }
        }
      }
    } catch (error) {
      console.error(`Error scanning directory ${dir}:`, error);
    }
  }

  await scanDirectory(projectPath);
  return files;
}

async function parseFile(filePath: string): Promise<ApiEndpoint[]> {
  const content = fs.readFileSync(filePath, 'utf8');
  const lines = content.split('\n');
  const endpoints: ApiEndpoint[] = [];
  const ext = path.extname(filePath).toLowerCase();

  for (let i = 0; i < lines.length; i++) {
    const line = lines[i].trim();
    
    // Look for API patterns based on file type
    if (ext === '.java' && isJavaApiPattern(line)) {
      const endpoint = parseJavaEndpoint(lines, i, filePath);
      if (endpoint) endpoints.push(endpoint);
    } else if (ext === '.py' && isPythonApiPattern(line)) {
      const endpoint = parsePythonEndpoint(lines, i, filePath);
      if (endpoint) endpoints.push(endpoint);
    } else if ((ext === '.js' || ext === '.ts') && isJavaScriptApiPattern(line)) {
      const endpoint = parseJavaScriptEndpoint(lines, i, filePath);
      if (endpoint) endpoints.push(endpoint);
    } else if ((ext === '.graphql' || ext === '.gql' || ext === '.graphqls') && isGraphQLPattern(line)) {
      const endpoint = parseGraphQLEndpoint(lines, i, filePath);
      if (endpoint) endpoints.push(endpoint);
    }
  }

  return endpoints;
}

function isJavaApiPattern(line: string): boolean {
  return line.includes('@RequestMapping') || 
         line.includes('@GetMapping') || 
         line.includes('@PostMapping') || 
         line.includes('@PutMapping') || 
         line.includes('@DeleteMapping') ||
         line.includes('@PatchMapping');
}

function isPythonApiPattern(line: string): boolean {
  return line.includes('@app.route') || 
         line.includes('@router.') ||
         line.includes('@api.') ||
         line.includes('@bp.route');
}

function isJavaScriptApiPattern(line: string): boolean {
  return line.includes('app.get(') || 
         line.includes('app.post(') || 
         line.includes('app.put(') || 
         line.includes('app.delete(') ||
         line.includes('app.patch(') ||
         line.includes('router.get(') ||
         line.includes('router.post(') ||
         line.includes('router.put(') ||
         line.includes('router.delete(') ||
         line.includes('router.patch(') ||
         line.includes('@Get(') ||
         line.includes('@Post(') ||
         line.includes('@Put(') ||
         line.includes('@Delete(') ||
         line.includes('@Patch(');
}

function isGraphQLPattern(line: string): boolean {
  return line.startsWith('type ') || 
         line.startsWith('input ') || 
         line.startsWith('enum ') ||
         line.startsWith('query ') ||
         line.startsWith('mutation ') ||
         line.startsWith('subscription ');
}

function parseJavaEndpoint(lines: string[], startLine: number, filePath: string): ApiEndpoint | null {
  const line = lines[startLine];
  let method = 'GET';
  let path = '';
  let description = '';
  let parameters: ApiParameter[] = [];
  let returnType = 'void';
  let returnDescription = '';

  // Extract HTTP method and path from annotation
  if (line.includes('@GetMapping')) {
    method = 'GET';
    path = extractJavaPath(line);
  } else if (line.includes('@PostMapping')) {
    method = 'POST';
    path = extractJavaPath(line);
  } else if (line.includes('@PutMapping')) {
    method = 'PUT';
    path = extractJavaPath(line);
  } else if (line.includes('@DeleteMapping')) {
    method = 'DELETE';
    path = extractJavaPath(line);
  } else if (line.includes('@PatchMapping')) {
    method = 'PATCH';
    path = extractJavaPath(line);
  } else if (line.includes('@RequestMapping')) {
    method = extractJavaMethod(line);
    path = extractJavaPath(line);
  }

  // Look for method signature in next few lines
  let methodName = '';
  for (let i = startLine + 1; i < Math.min(startLine + 10, lines.length); i++) {
    const methodLine = lines[i];
    if (methodLine.includes('public') && methodLine.includes('(')) {
      methodName = extractJavaMethodName(methodLine);
      returnType = extractJavaReturnType(methodLine);
      parameters = extractJavaParameters(methodLine);
      break;
    }
  }

  // Look for JavaDoc comments above the annotation
  for (let i = startLine - 1; i >= Math.max(0, startLine - 10); i--) {
    const commentLine = lines[i];
    if (commentLine.includes('/**')) {
      description = extractJavaDocDescription(lines, i);
      break;
    }
  }

  if (!methodName) {
    return null;
  }

  const examples = generateJavaExamples(method, path, parameters, returnType);

  return {
    name: methodName,
    path,
    method,
    description: description || `${method} endpoint for ${methodName}`,
    parameters,
    returnType,
    returnDescription,
    examples,
    filePath,
    lineNumber: startLine + 1
  };
}

function parsePythonEndpoint(lines: string[], startLine: number, filePath: string): ApiEndpoint | null {
  const line = lines[startLine];
  let method = 'GET';
  let path = '';
  let description = '';
  let parameters: ApiParameter[] = [];
  let returnType = 'dict';
  let returnDescription = '';

  // Extract path and method from decorator
  if (line.includes('@app.route') || line.includes('@router.') || line.includes('@bp.route')) {
    path = extractPythonPath(line);
    method = extractPythonMethod(line);
  } else if (line.includes('@api.')) {
    path = extractFastAPIPath(line);
    method = extractFastAPIMethod(line);
  }

  // Look for function definition in next few lines
  let functionName = '';
  for (let i = startLine + 1; i < Math.min(startLine + 10, lines.length); i++) {
    const funcLine = lines[i];
    if (funcLine.includes('def ') && funcLine.includes('(')) {
      functionName = extractPythonFunctionName(funcLine);
      parameters = extractPythonParameters(funcLine);
      returnType = extractPythonReturnType(funcLine);
      break;
    }
  }

  // Look for docstring
  for (let i = startLine + 1; i < Math.min(startLine + 20, lines.length); i++) {
    const docLine = lines[i];
    if (docLine.includes('"""') || docLine.includes("'''")) {
      description = extractPythonDocstring(lines, i);
      break;
    }
  }

  if (!functionName) {
    return null;
  }

  const examples = generatePythonExamples(method, path, parameters, returnType);

  return {
    name: functionName,
    path,
    method,
    description: description || `${method} endpoint for ${functionName}`,
    parameters,
    returnType,
    returnDescription,
    examples,
    filePath,
    lineNumber: startLine + 1
  };
}

function parseJavaScriptEndpoint(lines: string[], startLine: number, filePath: string): ApiEndpoint | null {
  const line = lines[startLine];
  let method = 'GET';
  let path = '';
  let description = '';
  let parameters: ApiParameter[] = [];
  let returnType = 'Object';
  let returnDescription = '';

  // Extract HTTP method and path
  if (line.includes('app.get(') || line.includes('router.get(') || line.includes('@Get(')) {
    method = 'GET';
    path = extractJavaScriptPath(line);
  } else if (line.includes('app.post(') || line.includes('router.post(') || line.includes('@Post(')) {
    method = 'POST';
    path = extractJavaScriptPath(line);
  } else if (line.includes('app.put(') || line.includes('router.put(') || line.includes('@Put(')) {
    method = 'PUT';
    path = extractJavaScriptPath(line);
  } else if (line.includes('app.delete(') || line.includes('router.delete(') || line.includes('@Delete(')) {
    method = 'DELETE';
    path = extractJavaScriptPath(line);
  } else if (line.includes('app.patch(') || line.includes('router.patch(') || line.includes('@Patch(')) {
    method = 'PATCH';
    path = extractJavaScriptPath(line);
  }

  // Look for function definition in next few lines
  let functionName = '';
  for (let i = startLine + 1; i < Math.min(startLine + 5, lines.length); i++) {
    const funcLine = lines[i];
    if (funcLine.includes('function') || funcLine.includes('=>') || funcLine.includes('(req, res)')) {
      functionName = extractJavaScriptFunctionName(funcLine, startLine);
      parameters = extractJavaScriptParameters(funcLine);
      break;
    }
  }

  // Look for JSDoc comments above the route
  for (let i = startLine - 1; i >= Math.max(0, startLine - 10); i--) {
    const commentLine = lines[i];
    if (commentLine.includes('/**')) {
      description = extractJSDocDescription(lines, i);
      break;
    }
  }

  if (!functionName) {
    functionName = `${method.toLowerCase()}Handler`;
  }

  const examples = generateJavaScriptExamples(method, path, parameters, returnType);

  return {
    name: functionName,
    path,
    method,
    description: description || `${method} endpoint for ${functionName}`,
    parameters,
    returnType,
    returnDescription,
    examples,
    filePath,
    lineNumber: startLine + 1
  };
}

// Helper functions for Java parsing
function extractJavaPath(line: string): string {
  const pathMatch = line.match(/value\s*=\s*["']([^"']+)["']/);
  if (pathMatch) {
    return pathMatch[1];
  }
  
  const pathMatch2 = line.match(/["']([^"']+)["']/);
  if (pathMatch2) {
    return pathMatch2[1];
  }
  
  return '/';
}

function extractJavaMethod(line: string): string {
  if (line.includes("method = RequestMethod.GET")) return 'GET';
  if (line.includes("method = RequestMethod.POST")) return 'POST';
  if (line.includes("method = RequestMethod.PUT")) return 'PUT';
  if (line.includes("method = RequestMethod.DELETE")) return 'DELETE';
  if (line.includes("method = RequestMethod.PATCH")) return 'PATCH';
  return 'GET';
}

function extractJavaMethodName(line: string): string {
  const match = line.match(/(\w+)\s*\(/);
  return match ? match[1] : 'unknown';
}

function extractJavaReturnType(line: string): string {
  const match = line.match(/public\s+([^\s]+)/);
  return match ? match[1] : 'void';
}

function extractJavaParameters(line: string): ApiParameter[] {
  const params: ApiParameter[] = [];
  const paramMatch = line.match(/\(([^)]+)\)/);
  
  if (paramMatch) {
    const paramString = paramMatch[1];
    const paramList = paramString.split(',').map(p => p.trim());
    
    for (const param of paramList) {
      if (param && param !== '') {
        const parts = param.split(/\s+/);
        if (parts.length >= 2) {
          const type = parts[0];
          const name = parts[1].replace(/[^\w]/g, '');
          
          params.push({
            name,
            type,
            description: `Parameter ${name} of type ${type}`,
            required: true
          });
        }
      }
    }
  }
  
  return params;
}

function extractJavaDocDescription(lines: string[], startLine: number): string {
  let description = '';
  
  for (let i = startLine; i < lines.length; i++) {
    const line = lines[i];
    if (line.includes('*/')) break;
    
    if (line.includes('*')) {
      const content = line.replace(/^\s*\*\s*/, '').trim();
      if (content && !content.startsWith('@')) {
        description += content + ' ';
      }
    }
  }
  
  return description.trim();
}

// Helper functions for Python parsing
function extractPythonPath(line: string): string {
  const pathMatch = line.match(/["']([^"']+)["']/);
  return pathMatch ? pathMatch[1] : '/';
}

function extractPythonMethod(line: string): string {
  if (line.includes("methods=['POST']") || line.includes('methods=["POST"]')) return 'POST';
  if (line.includes("methods=['PUT']") || line.includes('methods=["PUT"]')) return 'PUT';
  if (line.includes("methods=['DELETE']") || line.includes('methods=["DELETE"]')) return 'DELETE';
  if (line.includes("methods=['PATCH']") || line.includes('methods=["PATCH"]')) return 'PATCH';
  return 'GET';
}

function extractFastAPIPath(line: string): string {
  const pathMatch = line.match(/@api\.(get|post|put|delete|patch)\(["']([^"']+)["']/);
  return pathMatch ? pathMatch[2] : '/';
}

function extractFastAPIMethod(line: string): string {
  if (line.includes('@api.get')) return 'GET';
  if (line.includes('@api.post')) return 'POST';
  if (line.includes('@api.put')) return 'PUT';
  if (line.includes('@api.delete')) return 'DELETE';
  if (line.includes('@api.patch')) return 'PATCH';
  return 'GET';
}

function extractPythonFunctionName(line: string): string {
  const match = line.match(/def\s+(\w+)\s*\(/);
  return match ? match[1] : 'unknown';
}

function extractPythonParameters(line: string): ApiParameter[] {
  const params: ApiParameter[] = [];
  const paramMatch = line.match(/def\s+\w+\s*\(([^)]*)\)/);
  
  if (paramMatch) {
    const paramString = paramMatch[1];
    const paramList = paramString.split(',').map(p => p.trim());
    
    for (const param of paramList) {
      if (param && param !== '' && param !== 'self' && param !== 'cls') {
        const parts = param.split(':');
        const name = parts[0].trim();
        const type = parts.length > 1 ? parts[1].trim() : 'Any';
        
        params.push({
          name,
          type,
          description: `Parameter ${name} of type ${type}`,
          required: true
        });
      }
    }
  }
  
  return params;
}

function extractPythonReturnType(line: string): string {
  const returnMatch = line.match(/->\s*([^:]+)/);
  return returnMatch ? returnMatch[1].trim() : 'dict';
}

function extractPythonDocstring(lines: string[], startLine: number): string {
  let description = '';
  let inDocstring = false;
  
  for (let i = startLine; i < lines.length; i++) {
    const line = lines[i];
    
    if (line.includes('"""') || line.includes("'''")) {
      if (!inDocstring) {
        inDocstring = true;
        const content = line.replace(/^.*["']{3}/, '').replace(/["']{3}.*$/, '').trim();
        if (content) description += content + ' ';
      } else {
        break;
      }
    } else if (inDocstring) {
      description += line.trim() + ' ';
    }
  }
  
  return description.trim();
}

// Helper functions for JavaScript parsing
function extractJavaScriptPath(line: string): string {
  const pathMatch = line.match(/["']([^"']+)["']/);
  return pathMatch ? pathMatch[1] : '/';
}

function extractJavaScriptFunctionName(line: string, startLine: number): string {
  const functionMatch = line.match(/function\s+(\w+)/);
  if (functionMatch) {
    return functionMatch[1];
  }

  const arrowMatch = line.match(/const\s+(\w+)\s*=/);
  if (arrowMatch) {
    return arrowMatch[1];
  }

  const varMatch = line.match(/var\s+(\w+)\s*=/);
  if (varMatch) {
    return varMatch[1];
  }

  const letMatch = line.match(/let\s+(\w+)\s*=/);
  if (letMatch) {
    return letMatch[1];
  }

  return `handler_${startLine}`;
}

function extractJavaScriptParameters(line: string): ApiParameter[] {
  const params: ApiParameter[] = [];
  
  // Common Express.js parameters
  params.push({
    name: 'req',
    type: 'Request',
    description: 'Express request object',
    required: true
  });

  params.push({
    name: 'res',
    type: 'Response',
    description: 'Express response object',
    required: true
  });

  // Look for additional parameters in function signature
  const paramMatch = line.match(/\(([^)]+)\)/);
  if (paramMatch) {
    const paramString = paramMatch[1];
    const paramList = paramString.split(',').map(p => p.trim());
    
    for (const param of paramList) {
      if (param && param !== 'req' && param !== 'res' && param !== '') {
        params.push({
          name: param,
          type: 'any',
          description: `Parameter ${param}`,
          required: true
        });
      }
    }
  }
  
  return params;
}

function extractJSDocDescription(lines: string[], startLine: number): string {
  let description = '';
  
  for (let i = startLine; i < lines.length; i++) {
    const line = lines[i];
    if (line.includes('*/')) break;
    
    if (line.includes('*')) {
      const content = line.replace(/^\s*\*\s*/, '').trim();
      if (content && !content.startsWith('@')) {
        description += content + ' ';
      }
    }
  }
  
  return description.trim();
}

// Example generation functions
function generateJavaExamples(method: string, path: string, parameters: ApiParameter[], returnType: string): ApiExample[] {
  const examples: ApiExample[] = [];

  // cURL example
  let curlExample = `curl -X ${method} "http://localhost:8080${path}"`;
  if (parameters.length > 0) {
    curlExample += ` \\\n  -H "Content-Type: application/json" \\\n  -d '{\n`;
    const paramData = parameters.map(p => `    "${p.name}": "value"`).join(',\n');
    curlExample += paramData + '\n  }';
  }

  examples.push({
    title: 'cURL Request',
    description: 'Example cURL request for this endpoint',
    code: curlExample,
    language: 'bash'
  });

  // Java example
  let javaExample = `// Using RestTemplate\nRestTemplate restTemplate = new RestTemplate();\n`;
  if (method === 'GET') {
    javaExample += `ResponseEntity<${returnType}> response = restTemplate.getForEntity("http://localhost:8080${path}", ${returnType}.class);`;
  } else {
    javaExample += `HttpHeaders headers = new HttpHeaders();\nheaders.setContentType(MediaType.APPLICATION_JSON);\n`;
    if (parameters.length > 0) {
      javaExample += `// Create request body\nMap<String, Object> requestBody = new HashMap<>();\n`;
      parameters.forEach(p => {
        javaExample += `requestBody.put("${p.name}", "value");\n`;
      });
      javaExample += `HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);\n`;
    } else {
      javaExample += `HttpEntity<String> request = new HttpEntity<>(headers);\n`;
    }
    javaExample += `ResponseEntity<${returnType}> response = restTemplate.exchange("http://localhost:8080${path}", HttpMethod.${method}, request, ${returnType}.class);`;
  }

  examples.push({
    title: 'Java RestTemplate',
    description: 'Example using Spring RestTemplate',
    code: javaExample,
    language: 'java'
  });

  return examples;
}

function generatePythonExamples(method: string, path: string, parameters: ApiParameter[], returnType: string): ApiExample[] {
  const examples: ApiExample[] = [];

  // cURL example
  let curlExample = `curl -X ${method} "http://localhost:5000${path}"`;
  if (parameters.length > 0) {
    curlExample += ` \\\n  -H "Content-Type: application/json" \\\n  -d '{\n`;
    const paramData = parameters.map(p => `    "${p.name}": "value"`).join(',\n');
    curlExample += paramData + '\n  }';
  }

  examples.push({
    title: 'cURL Request',
    description: 'Example cURL request for this endpoint',
    code: curlExample,
    language: 'bash'
  });

  // Python requests example
  let pythonExample = `import requests\n\n`;
  if (method === 'GET') {
    pythonExample += `response = requests.get("http://localhost:5000${path}")`;
  } else {
    pythonExample += `url = "http://localhost:5000${path}"\n`;
    if (parameters.length > 0) {
      pythonExample += `data = {\n`;
      parameters.forEach(p => {
        pythonExample += `    "${p.name}": "value",\n`;
      });
      pythonExample += `}\n`;
      pythonExample += `response = requests.${method.toLowerCase()}(url, json=data)`;
    } else {
      pythonExample += `response = requests.${method.toLowerCase()}(url)`;
    }
  }
  pythonExample += `\n\nprint(response.status_code)\nprint(response.json())`;

  examples.push({
    title: 'Python Requests',
    description: 'Example using Python requests library',
    code: pythonExample,
    language: 'python'
  });

  return examples;
}

function generateJavaScriptExamples(method: string, path: string, parameters: ApiParameter[], returnType: string): ApiExample[] {
  const examples: ApiExample[] = [];

  // cURL example
  let curlExample = `curl -X ${method} "http://localhost:3000${path}"`;
  if (method !== 'GET' && parameters.length > 2) { // More than req, res
    curlExample += ` \\\n  -H "Content-Type: application/json" \\\n  -d '{\n`;
    const paramData = parameters
      .filter(p => p.name !== 'req' && p.name !== 'res')
      .map(p => `    "${p.name}": "value"`)
      .join(',\n');
    curlExample += paramData + '\n  }';
  }

  examples.push({
    title: 'cURL Request',
    description: 'Example cURL request for this endpoint',
    code: curlExample,
    language: 'bash'
  });

  // JavaScript fetch example
  let jsExample = `// Using fetch API\n`;
  if (method === 'GET') {
    jsExample += `fetch("http://localhost:3000${path}")\n  .then(response => response.json())\n  .then(data => console.log(data));`;
  } else {
    jsExample += `fetch("http://localhost:3000${path}", {\n  method: "${method}",\n  headers: {\n    "Content-Type": "application/json",\n  },\n`;
    if (parameters.length > 2) {
      jsExample += `  body: JSON.stringify({\n`;
      const paramData = parameters
        .filter(p => p.name !== 'req' && p.name !== 'res')
        .map(p => `    ${p.name}: "value"`)
        .join(',\n');
      jsExample += paramData + '\n  })\n';
    }
    jsExample += `})\n  .then(response => response.json())\n  .then(data => console.log(data));`;
  }

  examples.push({
    title: 'JavaScript Fetch',
    description: 'Example using JavaScript fetch API',
    code: jsExample,
    language: 'javascript'
  });

  return examples;
}

function generateMarkdown(documentation: ApiDocumentation): string {
  let markdown = `# API Documentation

**Project**: ${documentation.projectName}
**Description**: ${documentation.projectDescription}
**Generated**: ${documentation.generatedAt.toLocaleString()}

## Summary

- **Total Endpoints**: ${documentation.endpoints.length}
- **Project**: ${documentation.projectName}

## Endpoints

`;

  documentation.endpoints.forEach((endpoint, index) => {
    markdown += `### ${index + 1}. ${endpoint.name}

**${endpoint.method}** \`${endpoint.path}\`

**Description**: ${endpoint.description}

**File**: \`${endpoint.filePath}:${endpoint.lineNumber}\`

**Return Type**: \`${endpoint.returnType}\`

`;

    if (endpoint.parameters.length > 0) {
      markdown += `#### Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
`;
      endpoint.parameters.forEach(param => {
        const required = param.required ? 'Yes' : 'No';
        markdown += `| ${param.name} | \`${param.type}\` | ${required} | ${param.description} |\n`;
      });
      markdown += '\n';
    }

    if (endpoint.examples.length > 0) {
      markdown += `#### Examples

`;
      endpoint.examples.forEach(example => {
        markdown += `**${example.title}**

${example.description}

\`\`\`${example.language}
${example.code}
\`\`\`

`;
      });
    }

    markdown += `---

`;
  });

  return markdown;
}

async function showDocumentationResults(documentation: ApiDocumentation): Promise<void> {
  const content = `# API Documentation for ${documentation.projectName}

Generated on: ${documentation.generatedAt.toLocaleString()}

## Summary
- Total endpoints: ${documentation.endpoints.length}
- Project: ${documentation.projectName}

## Endpoints

${documentation.endpoints.map((endpoint, index) => `
### ${index + 1}. ${endpoint.name}
- **Path**: ${endpoint.path}
- **Method**: ${endpoint.method}
- **Description**: ${endpoint.description}
- **File**: ${endpoint.filePath}:${endpoint.lineNumber}
- **Return Type**: ${endpoint.returnType}
- **Parameters**: ${endpoint.parameters.length}
`).join('\n')}

Use the command "Export API Docs to Markdown" to save this documentation to a file.
`;

  const document = await vscode.workspace.openTextDocument({
    content,
    language: 'markdown'
  });

  await vscode.window.showTextDocument(document);
}

function parseGraphQLEndpoint(lines: string[], startLine: number, filePath: string): ApiEndpoint | null {
  const line = lines[startLine];
  let method = 'QUERY';
  let path = '';
  let description = '';
  let parameters: ApiParameter[] = [];
  let returnType = 'Object';
  let returnDescription = '';

  // Parse GraphQL type definitions
  if (line.startsWith('type ')) {
    const typeMatch = line.match(/type\s+(\w+)\s*\{/);
    if (typeMatch) {
      const typeName = typeMatch[1];
      method = 'TYPE';
      path = `/graphql/type/${typeName}`;
      returnType = typeName;
      returnDescription = `GraphQL type ${typeName}`;
      
      // Parse fields
      for (let i = startLine + 1; i < lines.length; i++) {
        const fieldLine = lines[i].trim();
        if (fieldLine.includes('}')) break;
        
        if (fieldLine && !fieldLine.startsWith('#') && !fieldLine.startsWith('"""')) {
          const fieldMatch = fieldLine.match(/^(\w+)\s*:\s*([^!]+)(!?)(\s*#\s*(.+))?$/);
          if (fieldMatch) {
            const fieldName = fieldMatch[1];
            const fieldType = fieldMatch[2].trim();
            const isRequired = fieldMatch[3] === '!';
            const fieldDescription = fieldMatch[4] ? fieldMatch[4].trim() : `Field ${fieldName}`;

            parameters.push({
              name: fieldName,
              type: fieldType,
              description: fieldDescription,
              required: isRequired,
              source: 'field'
            });
          }
        }
      }
    }
  }
  
  // Parse GraphQL input definitions
  else if (line.startsWith('input ')) {
    const inputMatch = line.match(/input\s+(\w+)\s*\{/);
    if (inputMatch) {
      const inputName = inputMatch[1];
      method = 'INPUT';
      path = `/graphql/input/${inputName}`;
      returnType = inputName;
      returnDescription = `GraphQL input type ${inputName}`;
      
      // Parse input fields
      for (let i = startLine + 1; i < lines.length; i++) {
        const fieldLine = lines[i].trim();
        if (fieldLine.includes('}')) break;
        
        if (fieldLine && !fieldLine.startsWith('#') && !fieldLine.startsWith('"""')) {
          const fieldMatch = fieldLine.match(/^(\w+)\s*:\s*([^!]+)(!?)(\s*#\s*(.+))?$/);
          if (fieldMatch) {
            const fieldName = fieldMatch[1];
            const fieldType = fieldMatch[2].trim();
            const isRequired = fieldMatch[3] === '!';
            const fieldDescription = fieldMatch[4] ? fieldMatch[4].trim() : `Input field ${fieldName}`;

            parameters.push({
              name: fieldName,
              type: fieldType,
              description: fieldDescription,
              required: isRequired,
              source: 'input'
            });
          }
        }
      }
    }
  }
  
  // Parse GraphQL enum definitions
  else if (line.startsWith('enum ')) {
    const enumMatch = line.match(/enum\s+(\w+)\s*\{/);
    if (enumMatch) {
      const enumName = enumMatch[1];
      method = 'ENUM';
      path = `/graphql/enum/${enumName}`;
      returnType = enumName;
      returnDescription = `GraphQL enum ${enumName}`;
      
      // Parse enum values
      for (let i = startLine + 1; i < lines.length; i++) {
        const valueLine = lines[i].trim();
        if (valueLine.includes('}')) break;
        
        if (valueLine && !valueLine.startsWith('#') && !valueLine.startsWith('"""')) {
          const valueMatch = valueLine.match(/^(\w+)(\s*#\s*(.+))?$/);
          if (valueMatch) {
            const valueName = valueMatch[1];
            const valueDescription = valueMatch[2] ? valueMatch[2].trim() : `Enum value ${valueName}`;

            parameters.push({
              name: valueName,
              type: enumName,
              description: valueDescription,
              required: true,
              source: 'enum'
            });
          }
        }
      }
    }
  }
  
  // Parse GraphQL queries, mutations, and subscriptions
  else if (line.startsWith('query ') || line.startsWith('mutation ') || line.startsWith('subscription ')) {
    const queryMatch = line.match(/^(query|mutation|subscription)\s+(\w+)(\s*\(([^)]*)\))?\s*\{/);
    if (queryMatch) {
      const operationType = queryMatch[1].toUpperCase();
      const operationName = queryMatch[2];
      method = operationType;
      path = `/graphql/${operationType.toLowerCase()}/${operationName}`;
      
      // Parse parameters
      if (queryMatch[3]) {
        const paramString = queryMatch[3];
        const paramList = paramString.split(',').map(p => p.trim());
        
        for (const param of paramList) {
          if (param && param !== '') {
            const paramMatch = param.match(/^(\w+)\s*:\s*([^!]+)(!?)(\s*#\s*(.+))?$/);
            if (paramMatch) {
              const paramName = paramMatch[1];
              const paramType = paramMatch[2].trim();
              const isRequired = paramMatch[3] === '!';
              const paramDescription = paramMatch[4] ? paramMatch[4].trim() : `Parameter ${paramName}`;

              parameters.push({
                name: paramName,
                type: paramType,
                description: paramDescription,
                required: isRequired,
                source: 'query'
              });
            }
          }
        }
      }
      
      // Parse return type from query body
      for (let i = startLine + 1; i < lines.length; i++) {
        const queryLine = lines[i].trim();
        if (queryLine.includes('}')) break;
        
        if (queryLine && !queryLine.startsWith('#') && !queryLine.startsWith('"""')) {
          const fieldMatch = queryLine.match(/^(\w+)(\s*\{)?$/);
          if (fieldMatch) {
            returnType = fieldMatch[1];
            break;
          }
        }
      }
      
      returnDescription = `GraphQL ${operationType.toLowerCase()} result`;
    }
  }

  // Look for description above the definition
  for (let i = startLine - 1; i >= Math.max(0, startLine - 5); i--) {
    const commentLine = lines[i];
    if (commentLine.includes('"""') || commentLine.includes("'''")) {
      description = extractGraphQLDescription(lines, i);
      break;
    }
  }

  if (!path) {
    return null;
  }

  const examples = generateGraphQLExamples(method, path.split('/').pop() || '', parameters, returnType);

  return {
    name: path.split('/').pop() || 'unknown',
    path,
    method,
    description: description || `GraphQL ${method.toLowerCase()} definition`,
    parameters,
    returnType,
    returnDescription,
    examples,
    filePath,
    lineNumber: startLine + 1
  };
}

function extractGraphQLDescription(lines: string[], startLine: number): string {
  let description = '';
  let inDescription = false;
  
  for (let i = startLine; i < lines.length; i++) {
    const line = lines[i];
    
    if (line.includes('"""') || line.includes("'''")) {
      if (!inDescription) {
        inDescription = true;
        const content = line.replace(/^.*["']{3}/, '').replace(/["']{3}.*$/, '').trim();
        if (content) description += content + ' ';
      } else {
        break;
      }
    } else if (inDescription) {
      description += line.trim() + ' ';
    }
  }
  
  return description.trim();
}

function generateGraphQLExamples(operationType: string, operationName: string, parameters: ApiParameter[], returnType: string): ApiExample[] {
  const examples: ApiExample[] = [];

  // GraphQL schema example
  let graphqlExample = '';
  if (operationType === 'TYPE' || operationType === 'INPUT' || operationType === 'ENUM') {
    graphqlExample = `# ${operationType} definition\n`;
    graphqlExample += `${operationType.toLowerCase()} ${operationName} {\n`;
    parameters.forEach(param => {
      const required = param.required ? '!' : '';
      graphqlExample += `  ${param.name}: ${param.type}${required}\n`;
    });
    graphqlExample += `}`;
  } else {
    // Query/Mutation/Subscription
    graphqlExample = `${operationType.toLowerCase()} ${operationName}`;
    if (parameters.length > 0) {
      graphqlExample += `(\n`;
      parameters.forEach(param => {
        const required = param.required ? '!' : '';
        graphqlExample += `  $${param.name}: ${param.type}${required}\n`;
      });
      graphqlExample += `)`;
    }
    graphqlExample += ` {\n`;
    graphqlExample += `  # Query fields here\n`;
    graphqlExample += `}`;
  }

  examples.push({
    title: 'GraphQL Schema',
    description: `GraphQL ${operationType.toLowerCase()} definition`,
    code: graphqlExample,
    language: 'graphql'
  });

  // HTTP POST example for queries/mutations
  if (operationType === 'QUERY' || operationType === 'MUTATION') {
    let httpExample = `curl -X POST "http://localhost:4000/graphql" \\\n`;
    httpExample += `  -H "Content-Type: application/json" \\\n`;
    httpExample += `  -d '{\n`;
    httpExample += `    "query": "${operationType.toLowerCase()} ${operationName}`;
    
    if (parameters.length > 0) {
      httpExample += `(\n`;
      parameters.forEach(param => {
        const required = param.required ? '!' : '';
        httpExample += `      $${param.name}: ${param.type}${required}\n`;
      });
      httpExample += `    )`;
    }
    
    httpExample += ` {\n`;
    httpExample += `      # Query fields here\n`;
    httpExample += `    }\n`;
    httpExample += `  }'`;

    examples.push({
      title: 'HTTP POST Request',
      description: `HTTP POST request to GraphQL endpoint`,
      code: httpExample,
      language: 'bash'
    });
  }

  return examples;
} 